GdkGLContext: Change the way we track the current context
authorAlexander Larsson <alexl@redhat.com>
Thu, 30 Oct 2014 10:46:09 +0000 (11:46 +0100)
committerAlexander Larsson <alexl@redhat.com>
Thu, 30 Oct 2014 11:43:03 +0000 (12:43 +0100)
To properly support multithreaded use we use a global GPrivate
to track the current context. Since we also don't need to track
the current context on the display we move gdk_display_destroy_gl_context
to GdkGLContext::discard.

gdk/gdkdisplay.c
gdk/gdkdisplayprivate.h
gdk/gdkglcontext.c
gdk/gdkglcontextprivate.h
gdk/wayland/gdkdisplay-wayland.c
gdk/wayland/gdkglcontext-wayland.c
gdk/wayland/gdkglcontext-wayland.h
gdk/x11/gdkdisplay-x11.c
gdk/x11/gdkglcontext-x11.c
gdk/x11/gdkglcontext-x11.h

index acbf66fdee7663a114263b8dcfd447347d1744a4..d48491b611193f19cd82c4b0ee042edddc616618 100644 (file)
@@ -2244,28 +2244,6 @@ gdk_error_trap_pop (void)
   return gdk_error_trap_pop_internal (TRUE);
 }
 
-/*< private >
- * gdk_display_destroy_gl_context:
- * @display: a #GdkDisplay
- * @context: a #GdkGLContext
- *
- * Destroys the platform-specific parts of the @context.
- *
- * The @context instance is still valid, though inert, after
- * this functionr returns.
- */
-void
-gdk_display_destroy_gl_context (GdkDisplay   *display,
-                                GdkGLContext *context)
-{
-  GdkGLContext *current = gdk_display_get_current_gl_context (display);
-
-  if  (current == context)
-    g_object_set_data (G_OBJECT (display), "-gdk-gl-current-context", NULL);
-
-  GDK_DISPLAY_GET_CLASS (display)->destroy_gl_context (display, context);
-}
-
 /*< private >
  * gdk_display_make_gl_context_current:
  * @display: a #GdkDisplay
@@ -2274,35 +2252,9 @@ gdk_display_destroy_gl_context (GdkDisplay   *display,
  * Makes the given @context the current GL context, or unsets
  * the current GL context if @context is %NULL.
  */
-void
+gboolean
 gdk_display_make_gl_context_current (GdkDisplay   *display,
                                      GdkGLContext *context)
 {
-  GdkGLContext *current = gdk_display_get_current_gl_context (display);
-
-  if (current == context)
-    return;
-
-  if (context == NULL)
-    g_object_set_data (G_OBJECT (display), "-gdk-gl-current-context", NULL);
-  else
-    g_object_set_data_full (G_OBJECT (display), "-gdk-gl-current-context",
-                            g_object_ref (context),
-                            (GDestroyNotify) g_object_unref);
-
-  GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context);
-}
-
-/*< private >
- * gdk_display_get_current_gl_context:
- * @display: a #GdkDisplay
- *
- * Retrieves the current #GdkGLContext associated with @display.
- *
- * Returns: (transfer none): the current #GdkGLContext or %NULL
- */
-GdkGLContext *
-gdk_display_get_current_gl_context (GdkDisplay *display)
-{
-  return g_object_get_data (G_OBJECT (display), "-gdk-gl-current-context");
+  return GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context);
 }
index 6bd87d149c30bfe1c0f6d0d3a47106929d26b3c4..4c6f4a015bcf037c21459e1d342bfba0f7993dea 100644 (file)
@@ -228,10 +228,8 @@ struct _GdkDisplayClass
   gchar *                (*utf8_to_string_target)      (GdkDisplay     *display,
                                                         const gchar    *text);
 
-  void                  (*make_gl_context_current)  (GdkDisplay        *display,
-                                                     GdkGLContext      *context);
-  void                  (*destroy_gl_context)       (GdkDisplay        *display,
-                                                     GdkGLContext      *context);
+  gboolean               (*make_gl_context_current)    (GdkDisplay        *display,
+                                                        GdkGLContext      *context);
 
   /* Signals */
   void                   (*opened)                     (GdkDisplay     *display);
@@ -311,11 +309,8 @@ void                _gdk_display_create_window_impl   (GdkDisplay       *display
                                                        gint              attributes_mask);
 GdkWindow *         _gdk_display_create_window        (GdkDisplay       *display);
 
-void                gdk_display_destroy_gl_context       (GdkDisplay        *display,
+gboolean            gdk_display_make_gl_context_current  (GdkDisplay        *display,
                                                           GdkGLContext      *context);
-void                gdk_display_make_gl_context_current  (GdkDisplay        *display,
-                                                          GdkGLContext      *context);
-GdkGLContext *      gdk_display_get_current_gl_context   (GdkDisplay        *display);
 
 G_END_DECLS
 
index f1e87406e31d4ed4656816f168f4cec9037be4f4..748d9322dd2249cb78a623b278b0a5dfc3cd8985 100644 (file)
@@ -103,13 +103,18 @@ G_DEFINE_QUARK (gdk-gl-error-quark, gdk_gl_error)
 
 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkGLContext, gdk_gl_context, G_TYPE_OBJECT)
 
+static GPrivate thread_current_context = G_PRIVATE_INIT (g_object_unref);
+
 static void
 gdk_gl_context_dispose (GObject *gobject)
 {
   GdkGLContext *context = GDK_GL_CONTEXT (gobject);
   GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+  GdkGLContext *current;
 
-  gdk_display_destroy_gl_context (gdk_window_get_display (priv->window), context);
+  current = g_private_get (&thread_current_context);
+  if (current == context)
+    g_private_replace (&thread_current_context, NULL);
 
   g_clear_object (&priv->window);
   g_clear_object (&priv->visual);
@@ -310,13 +315,20 @@ void
 gdk_gl_context_make_current (GdkGLContext *context)
 {
   GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+  GdkGLContext *current;
 
   g_return_if_fail (GDK_IS_GL_CONTEXT (context));
 
-  gdk_display_make_gl_context_current (gdk_window_get_display (priv->window), context);
+  current = g_private_get (&thread_current_context);
+  if (current == context)
+    return;
 
-  if (!priv->realized)
-    gdk_gl_context_realize (context);
+  if (gdk_display_make_gl_context_current (gdk_window_get_display (priv->window), context))
+    {
+      g_private_replace (&thread_current_context, g_object_ref (context));
+      if (!priv->realized)
+        gdk_gl_context_realize (context);
+    }
 }
 
 /**
@@ -352,9 +364,16 @@ gdk_gl_context_get_window (GdkGLContext *context)
 void
 gdk_gl_context_clear_current (void)
 {
-  GdkDisplay *display = gdk_display_get_default ();
+  GdkGLContext *current;
 
-  gdk_display_make_gl_context_current (display, NULL);
+  current = g_private_get (&thread_current_context);
+  if (current != NULL)
+    {
+      GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (current);
+
+      if (gdk_display_make_gl_context_current (gdk_window_get_display (priv->window), NULL))
+        g_private_replace (&thread_current_context, NULL);
+    }
 }
 
 /**
@@ -369,7 +388,9 @@ gdk_gl_context_clear_current (void)
 GdkGLContext *
 gdk_gl_context_get_current (void)
 {
-  GdkDisplay *display = gdk_display_get_default ();
+  GdkGLContext *current;
+
+  current = g_private_get (&thread_current_context);
 
-  return gdk_display_get_current_gl_context (display);
+  return current;
 }
index c7b6937ba608cc86fad1bf27670a1df65e2df5bd..fcb82a834535331d126cba9ac50bdcca83077c17 100644 (file)
@@ -40,7 +40,7 @@ struct _GdkGLContextClass
 {
   GObjectClass parent_class;
 
-  void (* update)          (GdkGLContext *context);
+  void (* update)       (GdkGLContext *context);
   void (* end_frame)    (GdkGLContext *context,
                          cairo_region_t *painted,
                          cairo_region_t *damage);
index 0f367ec0d829a673fa165f6509d6ae1c44ee34e8..56e7278ee29567c36cb5806bf30cd2ecba5edae0 100644 (file)
@@ -534,7 +534,6 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass * class)
   display_class->text_property_to_utf8_list = _gdk_wayland_display_text_property_to_utf8_list;
   display_class->utf8_to_string_target = _gdk_wayland_display_utf8_to_string_target;
 
-  display_class->destroy_gl_context = gdk_wayland_display_destroy_gl_context;
   display_class->make_gl_context_current = gdk_wayland_display_make_gl_context_current;
 }
 
index 5fc320d9322d9e7eb44d03b2d78294fea008d03e..5a75c547481ad6f61f2642d077acbe55ea5322ec 100644 (file)
@@ -35,6 +35,8 @@
 
 G_DEFINE_TYPE (GdkWaylandGLContext, gdk_wayland_gl_context, GDK_TYPE_GL_CONTEXT)
 
+static void gdk_x11_gl_context_dispose (GObject *gobject);
+
 static void
 gdk_wayland_gl_context_update (GdkGLContext *context)
 {
@@ -159,9 +161,11 @@ static void
 gdk_wayland_gl_context_class_init (GdkWaylandGLContextClass *klass)
 {
   GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   context_class->update = gdk_wayland_gl_context_update;
   context_class->end_frame = gdk_wayland_gl_context_end_frame;
+  gobject_class->dispose = gdk_x11_gl_context_dispose;
 }
 
 static void
@@ -369,16 +373,18 @@ gdk_wayland_window_create_gl_context (GdkWindow     *window,
   return GDK_GL_CONTEXT (context);
 }
 
-void
-gdk_wayland_display_destroy_gl_context (GdkDisplay   *display,
-                                        GdkGLContext *context)
+static void
+gdk_x11_gl_context_dispose (GObject *gobject)
 {
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
-  GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
+  GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (gobject);
 
-  /* TODO: Unset as current if current? */
   if (context_wayland->egl_context != NULL)
     {
+      GdkGLContext *context = GDK_GL_CONTEXT (gobject);
+      GdkWindow *window = gdk_gl_context_get_window (context);
+      GdkDisplay *display = gdk_window_get_display (window);
+      GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
+
       if (eglGetCurrentContext () == context_wayland->egl_context)
         eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
                        EGL_NO_CONTEXT);
@@ -389,9 +395,11 @@ gdk_wayland_display_destroy_gl_context (GdkDisplay   *display,
                          context_wayland->egl_context);
       context_wayland->egl_context = NULL;
     }
+
+  G_OBJECT_CLASS (gdk_wayland_gl_context_parent_class)->dispose (gobject);
 }
 
-void
+gboolean
 gdk_wayland_display_make_gl_context_current (GdkDisplay   *display,
                                              GdkGLContext *context)
 {
@@ -404,7 +412,7 @@ gdk_wayland_display_make_gl_context_current (GdkDisplay   *display,
     {
       eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
                      EGL_NO_CONTEXT);
-      return;
+      return TRUE;
     }
 
   context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
@@ -422,6 +430,11 @@ gdk_wayland_display_make_gl_context_current (GdkDisplay   *display,
     }
 
   if (!eglMakeCurrent (display_wayland->egl_display, egl_surface,
-                      egl_surface, context_wayland->egl_context))
-    g_critical ("eglMakeCurrent failed");
+                       egl_surface, context_wayland->egl_context))
+    {
+      g_warning ("eglMakeCurrent failed");
+      return FALSE;
+    }
+
+  return TRUE;
 }
index 6a7d8797d8ccc2145c7356d7ef19276c8c6ae707..a140f5ca1504209facf8474b9fc2e0cf9d0a3a93 100644 (file)
@@ -55,9 +55,7 @@ GdkGLContext *  gdk_wayland_window_create_gl_context                (GdkWindow
                                                                      GError           **error);
 void            gdk_wayland_window_invalidate_for_new_frame         (GdkWindow         *window,
                                                                      cairo_region_t    *update_area);
-void            gdk_wayland_display_destroy_gl_context              (GdkDisplay        *display,
-                                                                     GdkGLContext      *context);
-void            gdk_wayland_display_make_gl_context_current         (GdkDisplay        *display,
+gboolean        gdk_wayland_display_make_gl_context_current         (GdkDisplay        *display,
                                                                      GdkGLContext      *context);
 
 G_END_DECLS
index 358ae84df07ee77ba339719488858ae2f165e0e2..220a85b009bc3a07c0ae4048630f26927c1e73d9 100644 (file)
@@ -2894,7 +2894,6 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class)
   display_class->text_property_to_utf8_list = _gdk_x11_display_text_property_to_utf8_list;
   display_class->utf8_to_string_target = _gdk_x11_display_utf8_to_string_target;
 
-  display_class->destroy_gl_context = gdk_x11_display_destroy_gl_context;
   display_class->make_gl_context_current = gdk_x11_display_make_gl_context_current;
 
   _gdk_x11_windowing_init ();
index 8d1e6cfe6101f958b3c8e901e7fab1af1f887e90..b7a90eb1774ffaec49812977a434b5a2adf82770 100644 (file)
@@ -495,14 +495,40 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
   return TRUE;
 }
 
+static void
+gdk_x11_gl_context_dispose (GObject *gobject)
+{
+  GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (gobject);
+
+  if (context_x11->glx_context != NULL)
+    {
+      GdkGLContext *context = GDK_GL_CONTEXT (gobject);
+      GdkWindow *window = gdk_gl_context_get_window (context);
+      GdkDisplay *display = gdk_window_get_display (window);
+      Display *dpy = gdk_x11_display_get_xdisplay (display);
+
+      if (glXGetCurrentContext () == context_x11->glx_context)
+        glXMakeContextCurrent (dpy, None, None, NULL);
+
+      GDK_NOTE (OPENGL, g_print ("Destroying GLX context\n"));
+      glXDestroyContext (dpy, context_x11->glx_context);
+      context_x11->glx_context = NULL;
+    }
+
+  G_OBJECT_CLASS (gdk_x11_gl_context_parent_class)->dispose (gobject);
+}
+
 static void
 gdk_x11_gl_context_class_init (GdkX11GLContextClass *klass)
 {
   GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   context_class->update = gdk_x11_gl_context_update;
   context_class->end_frame = gdk_x11_gl_context_end_frame;
   context_class->texture_from_surface = gdk_x11_gl_context_texture_from_surface;
+
+  gobject_class->dispose = gdk_x11_gl_context_dispose;
 }
 
 static void
@@ -1110,25 +1136,7 @@ gdk_x11_window_create_gl_context (GdkWindow    *window,
   return GDK_GL_CONTEXT (context);
 }
 
-void
-gdk_x11_display_destroy_gl_context (GdkDisplay   *display,
-                                    GdkGLContext *context)
-{
-  GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
-  Display *dpy = gdk_x11_display_get_xdisplay (display);
-
-  if (context_x11->glx_context != NULL)
-    {
-      if (glXGetCurrentContext () == context_x11->glx_context)
-        glXMakeContextCurrent (dpy, None, None, NULL);
-
-      GDK_NOTE (OPENGL, g_print ("Destroying GLX context\n"));
-      glXDestroyContext (dpy, context_x11->glx_context);
-      context_x11->glx_context = NULL;
-    }
-}
-
-void
+gboolean
 gdk_x11_display_make_gl_context_current (GdkDisplay   *display,
                                          GdkGLContext *context)
 {
@@ -1141,7 +1149,7 @@ gdk_x11_display_make_gl_context_current (GdkDisplay   *display,
   if (context == NULL)
     {
       glXMakeContextCurrent (dpy, None, None, NULL);
-      return;
+      return TRUE;
     }
 
   context_x11 = GDK_X11_GL_CONTEXT (context);
@@ -1161,8 +1169,13 @@ gdk_x11_display_make_gl_context_current (GdkDisplay   *display,
             g_print ("Making GLX context current to drawable %lu\n",
                      (unsigned long) context_x11->drawable));
 
-  glXMakeContextCurrent (dpy, context_x11->drawable, context_x11->drawable,
-                         context_x11->glx_context);
+  if (!glXMakeContextCurrent (dpy, context_x11->drawable, context_x11->drawable,
+                              context_x11->glx_context))
+    {
+      GDK_NOTE (OPENGL,
+                g_print ("Making GLX context current failed\n"));
+      return FALSE;
+    }
 
   if (context_x11->is_attached && GDK_X11_DISPLAY (display)->has_glx_swap_interval)
     {
@@ -1171,6 +1184,8 @@ gdk_x11_display_make_gl_context_current (GdkDisplay   *display,
       else
         glXSwapIntervalSGI (0);
     }
+
+  return TRUE;
 }
 
 /**
index 683ca41d001348478db579d86b0a30827ad542fb..865a7654a77a9b3bc74e7b1897ec2fed451de9d1 100644 (file)
@@ -64,9 +64,7 @@ GdkGLContext *  gdk_x11_window_create_gl_context                (GdkWindow
                                                                  GError           **error);
 void            gdk_x11_window_invalidate_for_new_frame         (GdkWindow         *window,
                                                                  cairo_region_t    *update_area);
-void            gdk_x11_display_destroy_gl_context              (GdkDisplay        *display,
-                                                                 GdkGLContext      *context);
-void            gdk_x11_display_make_gl_context_current         (GdkDisplay        *display,
+gboolean        gdk_x11_display_make_gl_context_current         (GdkDisplay        *display,
                                                                  GdkGLContext      *context);
 
 G_END_DECLS